package test;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.IImageMetadata;
import org.apache.commons.imaging.common.RationalNumber;
import org.apache.commons.imaging.common.IImageMetadata.IImageMetadataItem;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffField;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.constants.AllTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.MicrosoftTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.imaging.formats.tiff.fieldtypes.FieldType;
import org.apache.commons.imaging.formats.tiff.fieldtypes.FieldTypeByte;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfo;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;




public class ExifTest2 {

	/**
	 * @param args
	 * @throws IOException 
	 * @throws ImageReadException 
	 * @throws ImageWriteException 
	 * @throws ImageProcessingException 
	 */
	public static void main(String[] args) throws Exception {
		File file = new File("C:\\temp\\IMG_0217.JPG");

		// note that metadata might be null if no metadata is found.
		IImageMetadata metadata = Imaging.getMetadata(file);

		if (metadata instanceof JpegImageMetadata) {
			final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;

			// Jpeg EXIF metadata is stored in a TIFF-based directory structure
			// and is identified with TIFF tags.
			// Here we look for the "x resolution" tag, but
			// we could just as easily search for any other tag.
			//
			// see the TiffConstants file for a list of TIFF tags.

			System.out.println("file: " + file.getPath());

			// print out various interesting EXIF tags.
			printTagValue(jpegMetadata, MicrosoftTagConstants.EXIF_TAG_XPTITLE);
			
			printTagValue(jpegMetadata, TiffTagConstants.TIFF_TAG_XRESOLUTION);
			printTagValue(jpegMetadata, TiffTagConstants.TIFF_TAG_DATE_TIME);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_ISO);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_SHUTTER_SPEED_VALUE);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_APERTURE_VALUE);
			printTagValue(jpegMetadata, ExifTagConstants.EXIF_TAG_BRIGHTNESS_VALUE);
			printTagValue(jpegMetadata, GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF);
			printTagValue(jpegMetadata, GpsTagConstants.GPS_TAG_GPS_LATITUDE);
			printTagValue(jpegMetadata, GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF);
			printTagValue(jpegMetadata, GpsTagConstants.GPS_TAG_GPS_LONGITUDE);

			System.out.println();

			// simple interface to GPS data
			final TiffImageMetadata exifMetadata = jpegMetadata.getExif();
			if (null != exifMetadata) {
				final TiffImageMetadata.GPSInfo gpsInfo = exifMetadata.getGPS();
				if (null != gpsInfo) {
					final String gpsDescription = gpsInfo.toString();
					final double longitude = gpsInfo.getLongitudeAsDegreesEast();
					final double latitude = gpsInfo.getLatitudeAsDegreesNorth();

					System.out.println("    " + "GPS Description: " + gpsDescription);
					System.out.println("    " + "GPS Longitude (Degrees East): " + longitude);
					System.out.println("    " + "GPS Latitude (Degrees North): " + latitude);
				}
			}

			// more specific example of how to manually access GPS values
			final TiffField gpsLatitudeRefField = jpegMetadata.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF);
			final TiffField gpsLatitudeField = jpegMetadata.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE);
			final TiffField gpsLongitudeRefField = jpegMetadata.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF);
			final TiffField gpsLongitudeField = jpegMetadata.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE);
			if (gpsLatitudeRefField != null && gpsLatitudeField != null && gpsLongitudeRefField != null && gpsLongitudeField != null) {
				// all of these values are strings.
				final String gpsLatitudeRef = (String) gpsLatitudeRefField.getValue();
				final RationalNumber gpsLatitude[] = (RationalNumber[]) (gpsLatitudeField.getValue());
				final String gpsLongitudeRef = (String) gpsLongitudeRefField.getValue();
				final RationalNumber gpsLongitude[] = (RationalNumber[]) gpsLongitudeField.getValue();

				final RationalNumber gpsLatitudeDegrees = gpsLatitude[0];
				final RationalNumber gpsLatitudeMinutes = gpsLatitude[1];
				final RationalNumber gpsLatitudeSeconds = gpsLatitude[2];

				final RationalNumber gpsLongitudeDegrees = gpsLongitude[0];
				final RationalNumber gpsLongitudeMinutes = gpsLongitude[1];
				final RationalNumber gpsLongitudeSeconds = gpsLongitude[2];

				// This will format the gps info like so:
				//
				// gpsLatitude: 8 degrees, 40 minutes, 42.2 seconds S
				// gpsLongitude: 115 degrees, 26 minutes, 21.8 seconds E

				System.out.println("    " + "GPS Latitude: " + gpsLatitudeDegrees.toDisplayString() + " degrees, " + gpsLatitudeMinutes.toDisplayString() + " minutes, "
						+ gpsLatitudeSeconds.toDisplayString() + " seconds " + gpsLatitudeRef);
				System.out.println("    " + "GPS Longitude: " + gpsLongitudeDegrees.toDisplayString() + " degrees, " + gpsLongitudeMinutes.toDisplayString() + " minutes, "
						+ gpsLongitudeSeconds.toDisplayString() + " seconds " + gpsLongitudeRef);

			}

			System.out.println();

			final List<IImageMetadataItem> items = jpegMetadata.getItems();
			for (int i = 0; i < items.size(); i++) {
				final IImageMetadataItem item = items.get(i);
				System.out.println("    " + "item: " + item);
				System.out.println(item.getClass());
				TiffImageMetadata.Item item2 = (TiffImageMetadata.Item)item;
				System.out.println(item2.getTiffField().getCount());
				System.out.println(item2.getTiffField().getTagInfo().tag);
				System.out.println(item2.getTiffField().getFieldTypeName());
				System.out.println(item2.getTiffField().getTagInfo().length);
				System.out.println(item2.getTiffField().getDirectoryType());
			}

			System.out.println();		
		}

	}
	
	private static void printTagValue(final JpegImageMetadata jpegMetadata, final TagInfo tagInfo) {
		final TiffField field = jpegMetadata.findEXIFValueWithExactMatch(tagInfo);
		if (field == null) {
			System.out.println(tagInfo.name + ": " + "Not Found.");
		} else {
			System.out.println(tagInfo.name + ": " + field.getValueDescription());
		}
	}
}